package games.gong.durid.security;

/**
 * @ClassName JwtAuthFilter
 * @PackageName games.gong.durid.security
 * @projectName springboot
 * @Description JWT认证过滤器，用于拦截请求并验证JWT Token的有效性，若有效则设置Spring Security上下文中的认证信息
 * @Author games
 * @Date 2025/8/19 下午4:27
 * @Version 1.0
 */
import io.jsonwebtoken.JwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Collections;

@Component
public class JwtAuthFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(JwtAuthFilter.class);

    private final JwtUtil jwtUtil;

    /**
     * 构造函数，注入JwtUtil工具类
     *
     * @param jwtUtil JWT工具类实例，用于解析和生成JWT Token
     */
    public JwtAuthFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    /**
     * 过滤器核心方法，对每个HTTP请求进行JWT Token的解析与验证
     *
     * @param request  HTTP请求对象
     * @param response HTTP响应对象
     * @param chain    过滤器链，用于继续执行后续过滤器
     * @throws ServletException Servlet异常
     * @throws IOException      IO异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        // 获取请求头中的Authorization字段
        String header = request.getHeader("Authorization");
        // 判断是否以Bearer开头的JWT Token
        if (header != null && header.startsWith("Bearer ")) {
            // 提取Token内容
            String token = header.substring(7);
            try {
                // 解析Token获取Claims信息
                var claims = jwtUtil.parseToken(token).getBody();
                String username = claims.getSubject();
                Long userId = claims.get("id", Long.class);
                logger.info("UserId ---: {}", userId);

                // 创建认证对象并设置到Spring Security上下文中
                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } catch (JwtException e) {
                // 若Token无效，则返回401未授权状态码
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                // token 无效
            }
        }
        // 继续执行后续过滤器
        chain.doFilter(request, response);
    }
}
